/**
 * 
 */
package pe.bf.extranet.dao.impl;

import java.sql.CallableStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import javax.sql.DataSource;

import oracle.jdbc.OracleTypes;

import org.apache.log4j.Logger;

import pe.bf.base.dao.impl.BaseDAOImpl;
import pe.bf.base.types.OutParameter;
import pe.bf.domain.bean.Banco;
import pe.bf.domain.bean.Departamento;
import pe.bf.domain.bean.Distrito;
import pe.bf.domain.bean.Empresa;
import pe.bf.domain.bean.Moneda;
import pe.bf.domain.bean.Perfil;
import pe.bf.domain.bean.Provincia;
import pe.bf.domain.bean.TipoCuenta;
import pe.bf.domain.bean.TipoDocumento;
import pe.bf.domain.exceptions.DomainException;
import pe.bf.extranet.dao.MaestroDAO;

/**
 *  
 * 
 */
public class MaestroDAOImpl extends BaseDAOImpl implements MaestroDAO {

	Logger logger = Logger.getLogger(MaestroDAOImpl.class);

	static final String USP_LIS_TIPO_DOCUMENTO = "{call PGK_MAESTRO.USP_LIS_TIPO_DOCUMENTO(?)}";
	static final String USP_LIS_DISTRITO = "{call PGK_MAESTRO.USP_LIS_DISTRITO(?)}";
	static final String USP_LIS_EMPRESA = "{call PGK_MAESTRO.USP_LIS_EMPRESA(?)}";
	static final String USP_LIS_MONEDA = "{call PGK_MAESTRO.USP_LIS_MONEDA(?)}";
	static final String USP_LIS_TIPO_CUENTA = "{call PGK_MAESTRO.USP_LIS_TIPO_CUENTA(?)}";
	static final String USP_LIS_PERFIL = "{call PGK_MAESTRO.USP_LIS_PERFIL(?)}";
	static final String USP_LIS_BANCO = "{call PGK_MAESTRO.USP_LIS_BANCO(?)}";
	static final String USP_LIS_DEPARTAMENTOS = "{call PGK_MAESTRO.USP_LIS_DEPARTAMENTOS(?)}";
	static final String USP_LIS_PROVINCIAS = "{call PGK_MAESTRO.USP_LIS_PROVINCIAS(?,?)}";
	static final String USP_LIS_DISTRITOS = "{call PGK_MAESTRO.USP_LIS_DISTRITOS(?,?)}";

	/**
	 * 
	 * @param dataSource
	 */
	public MaestroDAOImpl(DataSource dataSource) {
		super(dataSource);
	}

	@Override
	public List<TipoDocumento> findTipoDocumentos() throws DomainException {
		CallableStatement cal = invokeStoreProcedureCallable(
				USP_LIS_TIPO_DOCUMENTO, new OutParameter(OracleTypes.CURSOR));
		List<TipoDocumento> listaTipoDocumento = new ArrayList<TipoDocumento>();
		try {
			ResultSet resultSet = null;
			resultSet = (ResultSet) cal.getObject(1);
			while (resultSet.next()) {
				TipoDocumento tipoDocumento = new TipoDocumento();
				tipoDocumento.setIdTipodocumento(resultSet.getLong(0));
				tipoDocumento.setDescripcion(resultSet.getString(1));
				tipoDocumento.setEstado(resultSet.getString(2));
				listaTipoDocumento.add(tipoDocumento);
			}
			return listaTipoDocumento;
		} catch (SQLException e) {
			e.printStackTrace();
			throw new DomainException(e);
		} finally {
			try {
				cal.getConnection().close();
				cal.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}

		}
	}

	@Override
	public List<Distrito> findDistritos() throws DomainException {
		CallableStatement cal = invokeStoreProcedureCallable(USP_LIS_DISTRITO,
				new OutParameter(OracleTypes.CURSOR));
		List<Distrito> listaDistrito = new ArrayList<Distrito>();
		try {
			ResultSet resultSet = null;
			resultSet = (ResultSet) cal.getObject(1);
			while (resultSet.next()) {
				Distrito distrito = new Distrito();
				distrito.setIdDistrito(resultSet.getLong(1));
				distrito.setDescripcion(resultSet.getString(2));
				distrito.setEstado(resultSet.getString(3));
				listaDistrito.add(distrito);
			}
			return listaDistrito;
		} catch (SQLException e) {
			logger.error(e, e.fillInStackTrace());
			throw new DomainException(e);
		} finally {
			try {
				cal.getConnection().close();
				cal.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}

		}
	}

	@Override
	public List<Empresa> findEmpresas() throws DomainException {
		CallableStatement cal = invokeStoreProcedureCallable(USP_LIS_EMPRESA,
				new OutParameter(OracleTypes.CURSOR));
		List<Empresa> listaEmpresa = new ArrayList<Empresa>();
		try {
			ResultSet resultSet = null;
			resultSet = (ResultSet) cal.getObject(1);
			while (resultSet.next()) {
				Empresa empresa = new Empresa();
				empresa.setIdEmpresa(resultSet.getLong(1));
				empresa.setDireccion(resultSet.getString(2));
				empresa.setEstado(resultSet.getString(3));
				empresa.setNombres(resultSet.getString(4));
				empresa.setRuc(resultSet.getString(5));
				empresa.setTelefono1(resultSet.getString(6));
				empresa.setTelefono2(resultSet.getString(7));
				listaEmpresa.add(empresa);
			}
			return listaEmpresa;
		} catch (SQLException e) {
			logger.error(e, e.fillInStackTrace());
			throw new DomainException(e);
		} finally {
			try {
				cal.getConnection().close();
				cal.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}

		}
	}

	@Override
	public List<Moneda> findMonedas() throws DomainException {
		CallableStatement cal = invokeStoreProcedureCallable(USP_LIS_MONEDA,
				new OutParameter(OracleTypes.CURSOR));
		List<Moneda> listaMoneda = new ArrayList<Moneda>();
		try {
			ResultSet resultSet = null;
			resultSet = (ResultSet) cal.getObject(1);
			while (resultSet.next()) {
				Moneda moneda = new Moneda();
				moneda.setIdMoneda(resultSet.getLong(1));
				moneda.setDescripcion(resultSet.getString(2));
				moneda.setEstado(resultSet.getString(3));
				listaMoneda.add(moneda);
			}
			return listaMoneda;
		} catch (SQLException e) {
			logger.error(e, e.fillInStackTrace());
			throw new DomainException(e);
		} finally {
			try {
				cal.getConnection().close();
				cal.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}

	@Override
	public List<TipoCuenta> findTipoCuentas() throws DomainException {
		CallableStatement cal = invokeStoreProcedureCallable(
				USP_LIS_TIPO_CUENTA, new OutParameter(OracleTypes.CURSOR));
		List<TipoCuenta> listaTipoCuenta = new ArrayList<TipoCuenta>();
		try {
			ResultSet resultSet = null;
			resultSet = (ResultSet) cal.getObject(1);
			while (resultSet.next()) {
				TipoCuenta tipoCuenta = new TipoCuenta();
				tipoCuenta
						.setIdTipocuenta(Long.valueOf(resultSet.getString(1)));
				tipoCuenta.setDescripcion(resultSet.getString(2));
				tipoCuenta.setEstado(resultSet.getString(3));
				listaTipoCuenta.add(tipoCuenta);
			}
			return listaTipoCuenta;
		} catch (SQLException e) {
			logger.error(e, e.fillInStackTrace());
			throw new DomainException(e);
		} finally {
			try {
				cal.getConnection().close();
				cal.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}

		}
	}

	@Override
	public List<Perfil> findPerfiles() throws DomainException {
		CallableStatement cal = invokeStoreProcedureCallable(USP_LIS_PERFIL,
				new OutParameter(OracleTypes.CURSOR));
		List<Perfil> listaPerfil = new ArrayList<Perfil>();
		try {
			ResultSet resultSet = null;
			resultSet = (ResultSet) cal.getObject(1);
			while (resultSet.next()) {
				Perfil perfil = new Perfil();
				perfil.setIdPerfil(resultSet.getLong(1));
				perfil.setDescripcion(resultSet.getString(2));
				listaPerfil.add(perfil);
			}
			return listaPerfil;
		} catch (SQLException e) {
			logger.error(e, e.fillInStackTrace());
			throw new DomainException(e);
		} finally {
			try {
				cal.getConnection().close();
				cal.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}

		}
	}

	@Override
	public List<Banco> findBancos() throws DomainException {
		CallableStatement cal = invokeStoreProcedureCallable(USP_LIS_BANCO,
				new OutParameter(OracleTypes.CURSOR));
		ResultSet resultSet = null;
		try {
			resultSet = (ResultSet) cal.getObject(1);

			List<Banco> lista = new ArrayList<Banco>();
			while (resultSet.next()) {
				Banco banco = new Banco();
				banco.setIdBanco(resultSet.getLong(1));
				banco.setDescripcion(resultSet.getString(2));
				lista.add(banco);
			}
			return lista;
		} catch (Exception e) {
			e.printStackTrace();
			throw new DomainException(e);
		} finally {
			try {
				cal.getConnection().close();
				cal.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}

		}
	}

	@Override
	public List<Departamento> findDepartamento() throws DomainException {
		CallableStatement cal = invokeStoreProcedureCallable(
				USP_LIS_DEPARTAMENTOS, new OutParameter(OracleTypes.CURSOR));
		ResultSet resultSet = null;
		try {
			resultSet = (ResultSet) cal.getObject(1);

			List<Departamento> lista = new ArrayList<Departamento>();
			while (resultSet.next()) {
				Departamento objeto = new Departamento();
				objeto.setIdDepartamento(resultSet.getLong(1));
				objeto.setDescripcion(resultSet.getString(2));
				lista.add(objeto);
			}
			return lista;
		} catch (Exception e) {
			e.printStackTrace();
			throw new DomainException(e);
		} finally {
			try {
				cal.getConnection().close();
				cal.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}

		}
	}

	public List<Provincia> findProvincia(String codigo) throws DomainException {
		CallableStatement cal = invokeStoreProcedureCallable(
				USP_LIS_PROVINCIAS, codigo,
				new OutParameter(OracleTypes.CURSOR));
		ResultSet resultSet = null;
		try {
			resultSet = (ResultSet) cal.getObject(2);

			List<Provincia> lista = new ArrayList<Provincia>();
			while (resultSet.next()) {
				Provincia objeto = new Provincia();
				objeto.setIdProvincia(resultSet.getLong(1));
				objeto.setDescripcion(resultSet.getString(2));
				lista.add(objeto);
			}
			return lista;
		} catch (Exception e) {
			e.printStackTrace();
			throw new DomainException(e);
		} finally {
			try {
				cal.getConnection().close();
				cal.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}

		}
	}

	public List<Distrito> findDistrito(String codigo) throws DomainException {
		CallableStatement cal = invokeStoreProcedureCallable(USP_LIS_DISTRITOS,
				codigo, new OutParameter(OracleTypes.CURSOR));
		ResultSet resultSet = null;
		try {
			resultSet = (ResultSet) cal.getObject(2);

			List<Distrito> lista = new ArrayList<Distrito>();
			while (resultSet.next()) {
				Distrito objeto = new Distrito();
				objeto.setIdDistrito(resultSet.getLong(1));
				objeto.setDescripcion(resultSet.getString(2));
				lista.add(objeto);
			}
			return lista;
		} catch (Exception e) {
			e.printStackTrace();
			throw new DomainException(e);
		} finally {
			try {
				cal.getConnection().close();
				cal.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}

		}
	}

}
